package org.leyi.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.leyi.shop.common.exception.BusinessException;
import org.leyi.shop.common.response.EnumResponse;
import org.leyi.shop.mapper.OrderMapper;
import org.leyi.shop.mapper.ProductMapper;
import org.leyi.shop.model.bo.OrderDelayItem;
import org.leyi.shop.model.pojo.Order;
import org.leyi.shop.model.pojo.Product;
import org.leyi.shop.model.vo.OrderVO;
import org.leyi.shop.service.OrderService;
import org.leyi.shop.util.IDRandomUtils;
import org.redisson.api.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Date;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static org.leyi.shop.common.Constant.*;

/**
 * @author lenovo
 * description 针对表【order(订单表)】的数据库操作Service实现
 * create 2024-05-04 23:19:17
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private ProductMapper productMapper;
    /**
     * 允许一个线程来实时监听消费队列;
     */
    private static Thread consumeOrderQueueThread;
    public void initConsumeOrderQueueThread() {
        consumeOrderQueueThread = new Thread(() -> {

            RBlockingQueue<OrderDelayItem> blockingFairQueue = redissonClient.getBlockingQueue(REDIS_QUEUE_FOR_STORING_USER_ORDERS);
            redissonClient.getDelayedQueue(blockingFairQueue);
            while (true) {
                try {
                    OrderDelayItem first = null;
                    first = blockingFairQueue.take();
                    this.addIntoOrderDatabase(1, first);
                    log.info("自动取消了"+first.getOrderId()+"的订单");
                } catch (InterruptedException e) {
                    break;
                }
            }
        });
    }
    @Override
    public void startConsumeOrderQueueThread() {
        initConsumeOrderQueueThread();
        consumeOrderQueueThread.start();
    }
    @Override
    public void stopConsumeOrderQueueThread() {
        if (consumeOrderQueueThread == null) {
            initConsumeOrderQueueThread();
        }
        if (!consumeOrderQueueThread.isInterrupted()) {
            consumeOrderQueueThread.interrupt();
        }
    }
    /**
     * description: 从延时队列中删除订单
     * @param orderId
     * @return OrderDelayItem
     * @author  lenovo
     * create by 2024/5/19-20:49
     */
    public OrderDelayItem removeById(Long orderId)
    {
        RBlockingQueue<OrderDelayItem> blockingFairQueue = redissonClient.getBlockingQueue(REDIS_QUEUE_FOR_STORING_USER_ORDERS);
        RDelayedQueue<OrderDelayItem> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
        OrderDelayItem orderDelayItem=null;
        //上锁，保证在用迭代器的时候防止其他线程对redis的延时队列进行操作，从而导致迭代器使用异常
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(REDIS_QUEUE_LOCK_FOR_STORING_USER_ORDERS);
        RLock writeLock = readWriteLock.writeLock();
        //上写锁
        writeLock.lock();
        try {
            Iterator<OrderDelayItem> iterator = delayedQueue.iterator();
            while (iterator.hasNext())
            {
                OrderDelayItem order = iterator.next();
                if(order.getOrderId().equals(orderId))
                {
                    orderDelayItem=order;
                    iterator.remove();
                    break;
                }
            }
        }catch (Exception e){
            throw new BusinessException(EnumResponse.SERVICE_REQUEST_ERR,"从延时队列删除订单失败");
        }
        finally {
            writeLock.unlock();
        }
        if(orderDelayItem==null)
        {
            log.info("不存在该订单");
            throw new BusinessException(EnumResponse.PARAMETER_ERR,"不存在该订单");
        }
        return orderDelayItem;
    }
    @Override
    public OrderDelayItem cancelOrder(Long orderId) {
        //执行取消逻辑
        //删除该订单
        //将该订单加入数据库
        OrderDelayItem orderDelayItem = removeById(orderId);
            this.addIntoOrderDatabase(1, orderDelayItem);
            log.info("订单取消成功了");

        return orderDelayItem;
    }

    /**
     * description: 操作数据库
     *
     * @param option
     * @param orderDelayItem
     * @author lenovo
     * create 2024/5/7-23:15
     */
    private void addIntoOrderDatabase(int option, OrderDelayItem orderDelayItem) {
        //取消的订单加入数据库option:1 付款 2
        if (option != 1 && option != 2) {
            throw new RuntimeException("函数输入的参数不对");
        }
        orderDelayItem.getOrderVOList().forEach(purchaseProduct -> {
            //不用校验数据了，在添加逻辑已经校验过了
            Order order = new Order();
            order.setId(IDRandomUtils.getDefaultId());
            order.setOrderId(orderDelayItem.getOrderId());
            order.setStoreId(purchaseProduct.getStoreId());
            order.setUserId(orderDelayItem.getUserId());
            order.setUserName(orderDelayItem.getUserName());
            order.setDormAddress(orderDelayItem.getDormAddress());
            order.setContact(orderDelayItem.getContact());
            order.setAfterSales(purchaseProduct.getAfterSales());
            order.setOrderState(option == 1 ? ORDER_STATE_CANCEL : ORDER_STATE_PAY);
            order.setProductId(purchaseProduct.getProductId());
            order.setProductName(purchaseProduct.getProductName());
            order.setPurchaseQuantity(purchaseProduct.getPurchaseQuantity());
            order.setProductPrice(purchaseProduct.getSellPrice());
            order.setCostPrice(purchaseProduct.getCostPrice());
            order.setUpdateTime(new Date());
            order.setCreateTime(orderDelayItem.getCreateTime());
            order.setDeleteLogic(0);
            //加入订单中
            transactionTemplate.execute((transactionStatus)->{
                    this.save(order);
            if (option == 1) {
                UpdateWrapper<Product> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("product_id", purchaseProduct.getProductId()).eq("store_id", purchaseProduct.getStoreId());
                //若是取消，还应该返还库存 并更新相应的字段 total_sell_quantity  product_quantity sell_quantity
                updateWrapper.setSql("product_quantity=product_quantity+" + purchaseProduct.getPurchaseQuantity())
                        .setSql("total_sell_quantity=total_sell_quantity-" + purchaseProduct.getPurchaseQuantity())
                        .setSql("sell_quantity=sell_quantity-" + purchaseProduct.getPurchaseQuantity());
                productMapper.update(updateWrapper);
            }
            return 0;
            });

        });
    }

    @Override
    public OrderDelayItem payOrder(Long orderId) {
        //校验微信成功支付的返回信息，若支付成功
        OrderDelayItem orderDelayItem=null;
        boolean isPay = true;
        if (isPay) {
            orderDelayItem=removeById(orderId);
            this.addIntoOrderDatabase(2, orderDelayItem);
            log.info(String.format("用户%d名为%s付款%f成功", orderDelayItem.getUserId(), orderDelayItem.getUserName(), orderDelayItem.getSum()));
        } else {
            throw new BusinessException(EnumResponse.PAY_FAIL, "付款失败了，请重试啊");
        }
        return orderDelayItem;

    }


    @Override
    public OrderDelayItem addOrder(OrderDelayItem orderDelayItem) {
        //为该订单设置订单号：
        orderDelayItem.setOrderId(IDRandomUtils.getOrderId());
        if (orderDelayItem.getUserId() <= 0) {
            throw new BusinessException(EnumResponse.PARAMETER_ERR);
        }
        if (orderDelayItem.getOrderVOList() == null || orderDelayItem.getOrderVOList().isEmpty()) {
            throw new BusinessException(EnumResponse.PARAMETER_ERR);
        }
        //操作业务
        RBlockingQueue<OrderDelayItem> blockingFairQueue = redissonClient.getBlockingQueue(REDIS_QUEUE_FOR_STORING_USER_ORDERS);
        RDelayedQueue<OrderDelayItem> delayedQueue = redissonClient.getDelayedQueue(blockingFairQueue);
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(REDIS_QUEUE_LOCK_FOR_STORING_USER_ORDERS);
        RLock writeLock = readWriteLock.writeLock();
        try {
            //利用迭代器来更新数据
            ListIterator<OrderVO> voListIterator = orderDelayItem.getOrderVOList().listIterator();
            while (voListIterator.hasNext()) {
                OrderVO purchaseProduct = voListIterator.next();
                //校验数据
                if (purchaseProduct.getProductId() <= 0 || purchaseProduct.getStoreId() <= 0) {
                    throw new BusinessException(EnumResponse.PARAMETER_ERR);
                }
                //查出并保存所有快照数据 是否支持售后，成本，售价，商品名称
                Product product = productMapper.selectOne(new QueryWrapper<Product>().eq("store_id", purchaseProduct.getStoreId()).eq("product_id", purchaseProduct.getProductId()));
                //判断是否下架或者库存不足
                if (product.getProductQuantity() < purchaseProduct.getPurchaseQuantity()) {
                    throw new BusinessException(EnumResponse.STORE_OUT_OF_STOCK, purchaseProduct.getProductName() + "库存不足啦，请重新下单");
                }
                if (product.getProductState() == PRODUCT_STATE_TAKE_OFF) {
                    throw new BusinessException(EnumResponse.PRODUCT_TAKEN_OFF, purchaseProduct.getProductName() + "已经被下架了");
                }
                purchaseProduct.setAfterSales(product.getAfterSales());
                purchaseProduct.setProductName(product.getProductName());
                purchaseProduct.setSellPrice(product.getSellPrice());
                purchaseProduct.setCostPrice(product.getCostPrice());
                //计算总价
                double sum = orderDelayItem.getSum();
                sum += purchaseProduct.getSellPrice() * purchaseProduct.getPurchaseQuantity();
                orderDelayItem.setSum(sum);
                //更新迭代器里的内容
                voListIterator.set(purchaseProduct);
                //在数据库里更改库存
                UpdateWrapper<Product> updateWrapper = new UpdateWrapper<>();
                updateWrapper.eq("product_id", purchaseProduct.getProductId()).eq("store_id", purchaseProduct.getStoreId());
                //并更新相应的字段 total_sell_quantity  product_quantity sell_quantity
                updateWrapper.setSql("product_quantity=product_quantity-" + purchaseProduct.getPurchaseQuantity())
                        .setSql("total_sell_quantity=total_sell_quantity+" + purchaseProduct.getPurchaseQuantity())
                        .setSql("sell_quantity=sell_quantity+" + purchaseProduct.getPurchaseQuantity());
                productMapper.update(updateWrapper);
            }
            //设定创建时间
            orderDelayItem.setCreateTime(new Date());
            //加入延迟队列
            //上写锁
            writeLock.lock();
            try {
                delayedQueue.offer(orderDelayItem, ORDER_COUNTDOWN, TimeUnit.SECONDS);
            }finally {
                writeLock.unlock();
            }
            return orderDelayItem;
        } finally {

        }
    }
}




